package com.wf.demo.job.controller;

import com.alibaba.fastjson.JSONObject;
import com.wf.demo.info.dao.DeviceDAO;
import com.wf.demo.info.pojo.*;
import com.wf.demo.info.service.*;
import com.wf.demo.info.util.Page4Navigator;
import com.wf.demo.info.util.Result;
import com.wf.demo.info.util.StatisticalUtil;
import com.wf.demo.job.netty.NettyServerHandler;
import com.wf.demo.job.pojo.DataDevice;
import com.wf.demo.job.pojo.LocationInfo;
import com.wf.demo.job.service.DataDeviceService;
import com.wf.demo.job.service.TimeOfDeviceService;
import com.wf.demo.job.util.JsonSearch;
import com.wf.demo.job.util.RedisUtil;
import com.wf.demo.sys.annotation.SysLog;
import com.wf.demo.sys.constant.CommonConstant;
import com.wf.demo.sys.pojo.User;
import com.wf.demo.sys.service.UserService;
import com.wf.demo.sys.util.CommonUtils;
import com.wf.demo.sys.util.JwtUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.xml.crypto.Data;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @Auther: wf
 * @Date: 2019/11/30 21:12
 * @Description:
 */
@RestController
public class ForeRESTController {
    @Autowired
    DataDeviceService dataDeviceService;
    @Autowired
    DeviceService deviceService;
    @Autowired
    DeviceDAO deviceDAO;
    @Autowired
    CompanyService companyService;
    @Autowired
    ModelService modelService;
    @Autowired
    RepairService repairService;
    @Autowired
    AlarmService alarmService;
    @Autowired
    TimeOfDeviceService timeOfDeviceService;
    @Autowired
    UserService userService;
    @Autowired
    RedisUtil redisUtil;
    @GetMapping("/forehome")
    @RequiresPermissions("job:forehome")
    public Object home( HttpServletRequest request) {
        //数据过滤功能
        String token = request.getHeader(CommonConstant.ACCESS_TOKEN);
        System.out.println(token);
        String username = JwtUtil.getUsername(token);
        User sysUser = userService.getByName(username);
        //得到账号的客户公司
        Company company=sysUser.getCompany();

        //得到公司下所有的设备包括不在线的，
        List<Device> devices;
        //因为得到设备包括不在线的，所有要提取出里面在线的设备，创建一个list来储存
        List<Device> onLineDevices;

        //设备过滤，id为1的红江厂总公司不可删除
        if (company.getId()==1) {
            //如果是红江厂总公司id=1，那么所有设备可见，
            onLineDevices=deviceDAO.findByIsOnline(true);
            devices=deviceDAO.findAll();
        } else {
            //否则根据公司进行数据过滤
             onLineDevices=deviceDAO.findByCompanyAndIsOnline(company,true);
             devices=deviceDAO.findByCompanyOrderById(company);
        }

        for (Device device:onLineDevices){
            //得到设备最新一个的数据
           List<DataDevice> dataDevices= dataDeviceService.getLatestData(device,1);
            //将数据集合给设备
            device.setDataDevices(dataDevices);
            //去掉数据集合里面每个数据的device信息
            dataDeviceService.removeDeviceFromData(device);
        }
       // StatisticalUtil su=deviceService.getAllStatisticalInfo();
        //统计
        StatisticalUtil su=deviceService.getSearchStatisticalInfo(devices);
        Map<String,Object> map= new HashMap<>();
        map.put("statistical",su);
        map.put("devices",onLineDevices);
        return  map;
    }
    @PostMapping("foresearch")
    @RequiresPermissions("job:foresearch")
    public Object search(@RequestBody JsonSearch jsonSearch,HttpServletRequest request){
        //数据过滤功能
        String token = request.getHeader(CommonConstant.ACCESS_TOKEN);
        System.out.println(token);
        String username = JwtUtil.getUsername(token);
        User sysUser = userService.getByName(username);
        //得到账号的客户公司
        Company company=sysUser.getCompany();

        //对客户公司增加数据过滤功能，如果该公司不是总公司，对搜索得到的设备要过滤,即对查询条件增加一个仅限于可供自己的公司
        if(company.getId()!= 1) {
            jsonSearch.setCompanyName(company.getName());
        }
        //得到搜索的设备
        List<Device> devices=deviceService.searchDevice(jsonSearch);

        //搜索得到设备包括不在线的，所有要提取出里面在线的设备，创建一个list来储存
        List<Device> onLineDevices=new ArrayList<>();

        if(devices.isEmpty()){
            String message ="没有满足条件的设备";
            return Result.searchFail(message);
        }
        for (Device device:devices){
            //提取里面所有在线的设备显示在地图上
            if(device.isOnline()){
                //得到设备最新一个的数据
                List<DataDevice> dataDevices =dataDeviceService.getLatestData(device,1);
                //将数据集合给设备
                device.setDataDevices(dataDevices);
                //去掉数据集合里面每个数据的device信息
                dataDeviceService.removeDeviceFromData(device);
                //放进集合中
                onLineDevices.add(device);
            }
        }
        StatisticalUtil su=deviceService.getSearchStatisticalInfo(devices);
        Map<String,Object> map= new HashMap<>();
        map.put("statistical",su);
        map.put("devices",onLineDevices);
        return Result.searchSuccess(map);
    }
    @GetMapping("/forSingleDevice/{did}")
    @RequiresPermissions("job:forSingleDevice")
    public Object getAllInfoDevice(@PathVariable("did")Long did ) {
        Device device =deviceService.get(did);
        //得到设备最新20个的数据
        List<DataDevice> dataDevices= dataDeviceService.getLatestData(device,20);
        /*//将数据集合给设备
        device.setDataDevices(dataDevices);*/
        //去掉数据集合里面每个数据的device信息
        dataDeviceService.removeDeviceFromDataNew(dataDevices);
        //得到三个repair信息
        List<Repair> repairs=repairService.getLatestRepaire(device,3);
        //得到三个alarm
        List<Alarm> alarms = alarmService.getLatestAlarms(device,3);
        //得到此设备的在线率月变化情况
        Map<String,Float> monthmap= (Map<String, Float>) timeOfDeviceService.statisticlMonthofOnlineRate(device);
        //得到设备的累计在线时间 正常时间和报警时间
        Map<String,Object> singleDeviceTimeMap= (Map<String, Object>) deviceService.getSingleDeviceTimeStatistical(device);
        //轨迹运动的变化，默认传输24个点，每个点是间隔一个小时的位置数据,
        //得到设备的所有数据page ，取24页 ,每个页大小为30个，即2*30为1个小时的数据，先取3个就好
        List<LocationInfo> locationInfos=dataDeviceService.getLocationChange(device,3,24);
        Map<String,Object> map= new HashMap<>();
        //map.put("device",device); 去掉，因为alarm中已经了包含了设备信息
        map.put("datas",dataDevices);
        map.put("repairs",repairs);
        map.put("alarms",alarms);
        map.put("monthOnlineRate",monthmap);
        map.put("DeviceTime",singleDeviceTimeMap);
        map.put("locationChange",locationInfos);
        return  map;
    }
    @GetMapping("forDeviceManagement")
    @RequiresPermissions("job:forDeviceManagement")
    public Object getDeviceManagement() {

        LocalDate localDate=LocalDate.now();
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
         //读取缓存中记录设备在线，报警一周的的数据
       LinkedHashMap<String,Object>  obj = new LinkedHashMap<>();
        for(long i=0;i<7;i++){
            String ss= df.format(localDate.minusDays(i));//减少天数
            StatisticalUtil result = (StatisticalUtil) redisUtil.get("statisticalUtil"  + ":"+ "statisticalUtil-"+ ss); //读取
            if (null !=result)
            obj.put(ss,result);
        }

        LinkedHashMap<String,Object> map= new  LinkedHashMap<>();
        //最近一周的数据,总数量 在线=正常+报警
        map.put("StatisticalInfo",obj);
        //每个公司下各机型具体数量的统计
        map.put("aboutCompany",companyService.statisticDeviceAndCompany());
        //每种机型下下各公司具体数量的统计
        map.put("aboutModel",modelService.statisticDeviceAndModel());
        //报废设备最大使用寿命、平均使用寿命、最小使用寿命
        map.put("scrapDeviceLife",deviceService.getStatisticalScrapDevice());
        //最新状态发生改变的20个设备
      //  map.put("devices",devices);
        //所有在线的设备带页面信息
      //  map.put("devices",devicePage);
        return  map;
    }
    //设备管理：搜索设备
    @PostMapping("forDeviceManagementSearch")
    @RequiresPermissions("job:forDeviceManagementSearch")
    public Object getDeviceManagementSearch(@RequestBody JsonSearch jsonSearch,
                                            @RequestParam(value = "start",defaultValue = "0")int start,
                                            @RequestParam(value ="size",defaultValue = "15")int size) {
        //根据搜索得到设备
        Page4Navigator<Device> devicesPage4Navigator=deviceService.searchDevice2(jsonSearch,start,size,5);
        for (Device device :devicesPage4Navigator.getContent()){
            device.setDataDevices(null);
        }
        if(devicesPage4Navigator.getContent().isEmpty()){
            return  Result.searchFail("没有满足条件的设备");
        }
        return  Result.searchSuccess(devicesPage4Navigator);
    }
    /**
     * 控制发动机停止工作
     *
     * */
    @SysLog("停止工作")
    @PutMapping("/forDeviceWorkS")
    @RequiresPermissions("job:stopWork")
    public Object stopWorkOfDevice(@RequestBody Map params) {
        long id= Long.parseLong(params.get("id").toString()) ;
        Device device=deviceService.get(id);
        //判断发动机是5G还是北斗
        if(null == device.getIpPort()){ //5G端口没有地址，说明为北斗传输
            //从redis中得到北斗的ip+port
          String url = (String) redisUtil.get("beidouTcpClientIp+Port");
          //先判断是否为空
          if (url.isEmpty()){
              return  Result.error(-1,"北斗传输的tcp客户端ip地址不存在");
          }
            String msg=" 16 27 88 90 12 45 31 15 41 ";
            //转码
            ByteBuf message= Unpooled.copiedBuffer(msg.getBytes());
            //执行设备控制    根据product.getUrl() 上个类写入map  的key  取到map中的 ChannelHandlerContext  执行writeAndFlush发送数据
            NettyServerHandler.map.get(url).channel().writeAndFlush(message);
        }
        else if (null != device.getIpPort()){//5G传输
            String url =device.getIpPort();
            String msg=" 16 27 88 90 12 45 31 15 41 ";
            //转码
            ByteBuf message= Unpooled.copiedBuffer(msg.getBytes());
            //执行设备控制    根据product.getUrl() 上个类写入map  的key  取到map中的 ChannelHandlerContext  执行writeAndFlush发送数据
            NettyServerHandler.map.get(url).channel().writeAndFlush(message);
        }
        else if(null == device.getIpPort() &&  null == device.getBeidouId()){
            return  Result.error(-1,"该设备的5G端口和北斗卡号都不存在");
        }
        //修改发动机的转动状态为停止
        device.setRotateStatus(0);
        deviceService.update(device);
        System.out.println("设备的id是"+params.get("id"));
        return  Result.ok(1,"已发送停止工作指令");
    }
    /**
     * 控制发动机恢复工作
     *
     * */
    @SysLog("恢复工作")
    @PutMapping("/forDeviceWorkR")
    @RequiresPermissions("job:recoveryWork")
    public Object recoveryWorkOfDevice(@RequestBody Map params) {

        long id= Long.parseLong(params.get("id").toString()) ;
        Device device=deviceService.get(id);
        //修改发动机的转动状态为恢复
        device.setRotateStatus(1);
        deviceService.update(device);
        System.out.println("设备的id是"+id);
        return  Result.ok(1,"已发送恢复工作指令");
    }

}
